use std::fmt::{Display, Formatter, Pointer};

#[derive(Debug)]
pub struct Word {
    pub word: String,
    pub explains: Vec<String>,
    pub sentences: Vec<ExampleSentence>,
    pub phrase: Vec<Phrase>,
    pub pronounce: Option<Pronounce>,
}


impl Word {
    pub fn new(word: String) -> Word {
        Word {
            word,
            explains: vec![],
            sentences: vec![],
            phrase: vec![],
            pronounce: None,
        }
    }
}

impl Display for Word {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        fn format_vec<T: Display>(vec: &Vec<T>) -> String {
            vec.iter().enumerate()
                .map(|(index, item)| {
                    let mut s = format!("{}.{}", index + 1, item);
                    if !s.ends_with("\n") { s = s + "\n" }
                    s
                })
                .collect()
        }
        let pronounce = match &self.pronounce {
            None => { "".to_string() }
            Some(pronounce) => { format!("{}", pronounce) }
        };
        write!(f, "{}\t{}\n释义:\n{}\n短语:\n{}\n例句：\n{}",
               self.word, pronounce,
               format_vec(&self.explains),
               format_vec(&self.phrase),
               format_vec(&self.sentences))
    }
}

#[derive(Debug)]
pub struct ExampleSentence {
    pub en: String,
    pub ch: String,
}

impl Display for ExampleSentence {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}\n{}\n", self.en, self.ch)
    }
}

#[derive(Debug)]
pub struct Phrase {
    pub en: String,
    pub ch: String,
}

impl Display for Phrase {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}\t{}\n", self.en, self.ch)
    }
}

#[derive(Debug)]
pub struct Pronounce {
    pub british: String,
    pub american: String,
}

impl Display for Pronounce {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "英:【{}】 美【{}】", self.british, self.american)
    }
}

